import logging
from contextlib import contextmanager
from sqlalchemy.orm import sessionmaker, scoped_session, exc, query

from src.db.table import my_engine, Order

LOG = logging.getLogger()


@contextmanager
def session_begin():
    session = get_session()
    try:
        yield session
        session.commit()
    except Exception as e:
        LOG.warning('session error={}'.format(e))
    finally:
        session.close()


def _update_values(ref, values):
    for k in values:
        setattr(ref, k, values[k])


def get_session():
    Session = sessionmaker(bind=my_engine)
    Session = scoped_session(Session)
    session = Session()
    # session.execute("PRAGMA foreign_keys=ON")
    return session


class TabLeOperator(object):
    def __init__(self, table_class):
        self.table_class = table_class

    def _get(self, ref_id, session=None, force_show_deleted=False):
        session = session or get_session()
        query = session.query(self.table_class).filter_by(id=ref_id)
        if not force_show_deleted:
            query = query.filter__by(deleted=False)
        table_ref = query.first()
        if not table_ref:
            msg = "No table record found with ID {}".format(ref_id)
            LOG.error(msg)
            raise exc.NoResultFound
        return table_ref

    def add(self, values):
        with session_begin() as session:
            table_ref = self.table_class()
            _update_values(table_ref, values)
            session.add(table_ref)

    def get(self, filters=None, force_show_deleted=False):
        filters = filters or {}
        if not force_show_deleted:
            filters['deleted'] = False
        session = get_session()
        query = session.query(self.table_class).filter_by(**filters)
        table_recodes = []
        for table_ref in query.all():
            table_recodes.append(table_ref)
        return table_recodes

    def update(self, value, filters=None, force_show_deleted=False):
        filters = filters or {}
        if not force_show_deleted:
            filters['deleted'] = False
        session = get_session()
        info = session.query(self.table_class).filter_by(**filters).first()
        _update_values(info, value)
        session.commit()

